import math
import wx
import numpy as np
from TireCuringOptimization import TireCuringOptimization
import pickle
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import csv
import datetime

class TireInputPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        # 下载背景图片
        self.original_image = wx.Image('D:/项目资料/轮胎硫化/图片1.png', wx.BITMAP_TYPE_ANY)
        image = self.original_image.Scale(1000, 800, wx.IMAGE_QUALITY_HIGH)
        # Convert the wx.Image back to wx.Bitmap
        self.background_image = wx.Bitmap(image)

        # 将绘制事件绑定到事件处理程序
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnResize)

        # 创建三个垂直布局管理器
        self.buttons_sizer = wx.BoxSizer(wx.VERTICAL)  # 按钮布局
        self.plot_sizer = wx.BoxSizer(wx.VERTICAL)  # 图像布局
        self.csv_sizer = wx.BoxSizer(wx.VERTICAL)  # CSV内容布局

        # 创建水平布局管理器，并添加按钮管理器和右侧区域（包含图像和CSV内容）的嵌套布局
        self.right_sizer = wx.BoxSizer(wx.VERTICAL)  # 右侧布局（含图像和CSV内容）
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)  # 主布局
        self.sizer.Add(self.buttons_sizer, 1, wx.EXPAND | wx.ALL, border=5)
        self.right_sizer.Add(self.plot_sizer, 1, wx.EXPAND | wx.ALL, border=5)  # 50% 用于绘图
        self.right_sizer.Add(self.csv_sizer, 1, wx.EXPAND | wx.ALL, border=5)  # 另外50% 用于显示CSV
        self.sizer.Add(self.right_sizer, 3, wx.EXPAND | wx.ALL, border=5)

        self.SetSizer(self.sizer)

        #下面部分是按钮的设置
        self.btn1 = wx.Button(self, label='硫化轮胎总量')
        self.btn1.Bind(wx.EVT_BUTTON, self.OnButton1)
        self.buttons_sizer.Add(self.btn1, flag=wx.ALL, border=5)
        self.btn1.SetMinSize((100, 80))  # 设置按钮大小
        self.btn1.SetForegroundColour('blue')  # 设置按钮文字颜色
        self.btn1.SetBackgroundColour('white')  # 设置按钮背景颜色

        self.btn2 = wx.Button(self, label='硫化机数量')
        self.btn2.Bind(wx.EVT_BUTTON, self.OnButton2)
        self.buttons_sizer.Add(self.btn2, flag=wx.ALL, border=5)
        self.btn2.SetMinSize((100, 80))  # 设置按钮大小
        self.btn2.SetForegroundColour('blue')  # 设置按钮文字颜色
        self.btn2.SetBackgroundColour('white')  # 设置按钮背景颜色

        self.btn3 = wx.Button(self, label='轮胎的型号数')
        self.btn3.Bind(wx.EVT_BUTTON, self.OnButton3)
        self.buttons_sizer.Add(self.btn3, flag=wx.ALL, border=5)
        self.btn3.SetMinSize((100, 80))  # 设置按钮大小
        self.btn3.SetForegroundColour('blue')  # 设置按钮文字颜色
        self.btn3.SetBackgroundColour('white')  # 设置按钮背景颜色

        self.btn4 = wx.Button(self, label='型号/数量')
        self.btn4.Bind(wx.EVT_BUTTON, self.OnButton4)
        self.buttons_sizer.Add(self.btn4, flag=wx.ALL, border=5)
        self.btn4.SetMinSize((100, 80))  # 设置按钮大小
        self.btn4.SetForegroundColour('blue')  # 设置按钮文字颜色
        self.btn4.SetBackgroundColour('white')  # 设置按钮背景颜色

        self.btn5 = wx.Button(self, label='结果展示')
        self.btn5.Bind(wx.EVT_BUTTON, self.on_draw_button_clicked)
        self.buttons_sizer.Add(self.btn5, flag=wx.ALL, border=5)
        self.btn5.SetMinSize((100, 80))  # 设置按钮大小
        self.btn5.SetForegroundColour('blue')  # 设置按钮文字颜色
        self.btn5.SetBackgroundColour('white')  # 设置按钮背景颜色

        # 创建CSV文件内容显示的控件
        self.csv_list_ctrl = wx.ListCtrl(self, style=wx.LC_REPORT | wx.BORDER_SUNKEN)
        self.csv_sizer.Add(self.csv_list_ctrl, 1, wx.EXPAND | wx.ALL, border=5)  # 添加到CSV布局管理器

        # 调用CSV加载功能
        self.load_csv_data('curing_sequence_matrix.csv')

    def load_csv_data(self, file_path):
        # 首先，检查文件是否存在
        try:
            with open(file_path, 'r', newline='', encoding='utf-8') as file:
                csv_reader = csv.reader(file)
                headers = next(csv_reader)  # 读取标题行

                # 为ListCtrl添加列头
                for index, header in enumerate(headers):
                    self.csv_list_ctrl.InsertColumn(index, header)

                # 读取CSV文件中的每一行
                for row in csv_reader:
                    index = self.csv_list_ctrl.InsertItem(self.csv_list_ctrl.GetItemCount(), row[0])  # 插入第一列数据
                    # 插入剩余的列数据
                    for i in range(1, len(row)):
                        self.csv_list_ctrl.SetItem(index, i, row[i])
        except Exception as e:
            print(f"Error loading CSV data: {e}")
            # 这里可以添加错误处理代码，比如显示一个错误对话框或者日志记录

    #按钮事件的处理
    def OnButton1(self, event):
        dlg = wx.NumberEntryDialog(self, '请输入硫化轮胎的总数量', '输入', '硫化轮胎数量', 0, 0, 10000)
        if dlg.ShowModal() == wx.ID_OK:
            self.tire_quantities = dlg.GetValue()
        dlg.Destroy()

    def OnButton2(self, event):
        dlg = wx.NumberEntryDialog(self, '请输入硫化机数量', '输入', '轮胎型号', 0, 0, 10000)
        if dlg.ShowModal() == wx.ID_OK:
            self.num_machines = dlg.GetValue()
        dlg.Destroy()

    def OnButton3(self, event):
        dlg = wx.NumberEntryDialog(self, '请输入轮胎的型号', '输入', '轮胎型号', 0, 0, 10000)
        if dlg.ShowModal() == wx.ID_OK:
            self.num_types = dlg.GetValue()
        dlg.Destroy()

    def OnButton4(self, event):
        self.pre_tire_quantities = np.zeros(self.num_types, dtype=np.int32)
        for i in range(self.num_types):
            dlg = wx.NumberEntryDialog(self, f'请输入型号{i + 1}轮胎的数量', '输入', f'型号{i + 1}轮胎数量', 0, 0,
                                       10000)
            if dlg.ShowModal() == wx.ID_OK:
                self.pre_tire_quantities[i] = dlg.GetValue()
            dlg.Destroy()

    def OnResize(self, event):
        # 调用Layout以确保调整面板的子项的大小
        self.Layout()

        # 检索面板的新尺寸
        new_width, new_height = self.GetSize()

        # 重新缩放原始图像以适应新的面板大小
        resized_image = self.original_image.Scale(new_width, new_height, wx.IMAGE_QUALITY_HIGH)
        self.background_image = wx.Bitmap(resized_image)
        # 重新绘制面板
        self.Refresh()
    def OnPaint(self, event):
        # 为图形创建设备上下文
        dc = wx.PaintDC(self)

        # 在面板上绘制重新缩放的背景图像
        dc.DrawBitmap(self.background_image, 0, 0, True)

    def on_draw_button_clicked(self, event):
        # 保存需要的数据到文件中
        with open('my_data.pkl', 'wb') as f:
            my_data = [self.num_machines, self.num_types, self.pre_tire_quantities]
            pickle.dump(my_data, f)

        # 从文件中取出需要的数据
        with open('my_data.pkl', 'rb') as f:
            num_machines, num_types, pre_tire_quantities = pickle.load(f)
        optimizer = TireCuringOptimization(num_machines, num_types, pre_tire_quantities)

        # CSV文件名
        filename = 'TireCuringData.csv'

        # 将整型数组转换为字符串列表
        pre_tire_quantities_strings = list(map(str, pre_tire_quantities.tolist()))

        # 生成时间戳
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')

        # 调用你的优化算法
        fitness_history, best_counts, best_fitness = optimizer.optimize()

        # 调用优化算法后，更新CSV列表控件显示最新的数据
        self.update_csv_list_ctrl('curing_sequence_matrix.csv')

        # 拼接所有数据，这里确保所有数据都是字符串
        data =[str(best_fitness)] + [timestamp] + [str(num_machines)] + [str(num_types)] + pre_tire_quantities_strings

        # 打开或创建CSV文件，并将数据追加到文件
        with open(filename, 'a', newline='') as csvfile:
            csvwriter = csv.writer(csvfile)

            # 如果文件是新创建的，则写入标题行
            if csvfile.tell() == 0:
                header = ['最小硫化时间', '时间', '硫化机数量', '轮胎型号数'] + \
                         ['型号' + str(i + 1) + '数量' for i in range(num_types)]
                csvwriter.writerow(header)

            # 写入数据行
            csvwriter.writerow(data)

        # 假设optimizer.plot_results返回一个figure的列表
        figures = optimizer.plot_results(fitness_history, best_counts)

        # 计算绘图窗格的行数和列数
        rows = 3
        cols = rows  # 采用方形布局

        grid_sizer = wx.GridSizer(rows, cols, 10, 10)  # 注意，这个sizer现在是grid_sizer
        for figure in figures:
            # 注意上面只是创建，这里将figure画到canvas上
            canvas = FigureCanvas(self, -1, figure)
            grid_sizer.Add(canvas, 1, wx.EXPAND)

        self.plot_sizer.Add(grid_sizer, 1, wx.EXPAND)  # 将GridSizer添加到垂直布局管理的绘图区

        self.Layout()  # 刷新布局，包括重新布局和重绘内容
        self.Fit()

    def update_csv_list_ctrl(self, file_path):
        # 首先清除现有数据
        self.csv_list_ctrl.DeleteAllItems()

        # 如果有列头，根据需要决定是否要删除并重建
        for i in range(self.csv_list_ctrl.GetColumnCount()):
            self.csv_list_ctrl.DeleteColumn(0)

        # 加载csv数据
        self.load_csv_data(file_path)

class TireInputFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title='输入排产信息', size=(400, 300))
        panel = TireInputPanel(self)

if __name__ == '__main__':
    app = wx.App(False)
    frame = TireInputFrame()
    frame.SetSize((1000, 800))
    frame.Show()
    app.MainLoop()